//
//  MAPYVpnManager.swift
//  Mars Proxy
//
//  Created by PowerfullClean on 2023/10/16.
//

import NetworkExtension

let mapy_proxyID = "com.marsproxy.fire.room.Mars-tunnel"
let mapy_serverAddress = "127.0.0.1"
let mapy_vpnStateChange_noti = NSNotification.Name.NEVPNStatusDidChange
let mapy_vpnlistUpdate_noti = NSNotification.Name("mapy_vpnlistUpdate_noti")
extension MAPYManager {
    // vpn权限弹窗
    func mapy_configVpnAuth(mapy_complete:((NETunnelProviderManager?, Error?) -> ())? = nil ) {
        NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
            if let mapy_error = error {
                mapy_complete?(nil, mapy_error)
                return
            }
            guard let managers = managers, let manager = managers.first else {
                mapy_complete?(nil, nil)
                return
            }
            self.mapy_vpnManager = manager
            // 初始化成功配置
            mapy_complete?(manager, nil)
        }
    }
    // 开始连接
    func mapy_startConnect(mapy_serverModel: MAPYServerModel?, mapy_complete: ((Bool)->())? = nil) {
        guard let mapy_serverModel = mapy_serverModel else {
            mapy_complete?(false)
            return }
        mapy_configVpnAuth { [self] mapy_manager, mapy_error in
            if let _ = mapy_error {
                mapy_complete?(false)
                return
            }
            guard let mapy_manager = mapy_manager else {
                let providerProtocol = NETunnelProviderProtocol()
                providerProtocol.providerBundleIdentifier = mapy_proxyID
                providerProtocol.serverAddress =  mapy_serverAddress
                providerProtocol.providerConfiguration = [:]
                let mapy_newManager = NETunnelProviderManager()
                mapy_newManager.protocolConfiguration = providerProtocol
                mapy_newManager.localizedDescription = "Martian Proxy"
                mapy_newManager.isEnabled = true
                mapy_newManager.saveToPreferences { err in
                    if let _ = err {
                        mapy_complete?(false)
                        return
                    }
                    mapy_newManager.loadFromPreferences { err in
                        if let _ = err {
                            mapy_complete?(false)
                            return
                        }
//                        if mapy_newManager.connection.status == .disconnected || mapy_newManager.connection.status == .invalid {
                            do {
                                let mapy_options = [
                                    "host": mapy_serverModel.mapy_address ?? "",
                                    "port": mapy_serverModel.mapy_port,
                                    "method": mapy_serverModel.mapy_method ?? "",
                                    "password": mapy_serverModel.mapy_password ?? ""
                                ]
                                try mapy_newManager.connection.startVPNTunnel(options: ["options": mapy_options as NSObject])
                                
                            } catch {
                                mapy_complete?(false)
                            }
//                        }
                    }
                }
                self.mapy_vpnManager = mapy_newManager
                mapy_complete?(false)
                return
            }
            
            mapy_manager.isEnabled = true
            self.mapy_vpnManager = mapy_manager
            if mapy_manager.connection.status == .connected {
                return
            }
//            if mapy_manager.connection.status == .disconnected || mapy_manager.connection.status == .invalid {
                do {
                    let mapy_options = [
                        "host": mapy_serverModel.mapy_address ?? "",
                        "port": mapy_serverModel.mapy_port ?? "",
                        "method": mapy_serverModel.mapy_method ?? "",
                        "password": mapy_serverModel.mapy_password ?? ""
                    ]
                    try mapy_manager.connection.startVPNTunnel(options: ["options": mapy_options as NSObject])
                    
                } catch {
                    mapy_complete?(false)
                }
//            }
        }
    }
    // 创建 vpn 管理对象
    func mapy_createVpnManager() {
        let providerProtocol = NETunnelProviderProtocol()
        providerProtocol.providerBundleIdentifier = mapy_proxyID
        providerProtocol.serverAddress = mapy_serverAddress
        providerProtocol.providerConfiguration = [:]
        let mapy_newManager = NETunnelProviderManager()
        mapy_newManager.protocolConfiguration = providerProtocol
        mapy_newManager.localizedDescription = "Martian Proxy"
        mapy_newManager.isEnabled = true
    }
    // 取消连接
    func mapy_stopConnect(mapy_complete: ((Bool)->())? = nil) {
        
        mapy_configVpnAuth {mapy_manager, mapy_error in
            if let _ = mapy_error {
                mapy_complete?(false)
                return
            }
            mapy_manager?.connection.stopVPNTunnel()
            mapy_complete?(true)
        }
    }
}

// vpn 通知
extension MAPYManager {
    @objc func mapy_addVPNChangeNoti() {
        NotificationCenter.default.addObserver(
            forName: mapy_vpnStateChange_noti,
            object: nil, queue: OperationQueue.main,
            using: {[weak self] mapy_noti in
                guard let mapy_self = self else { return }
                if let mapy_session = mapy_noti.object as? NETunnelProviderSession {
                    print(MAPYVpnStateType(rawValue: mapy_session.manager.connection.status.rawValue)?.mapy_title)
                    if mapy_self.mapy_vpnStateClickType == .mapy_connect { //如果点击了连接，只处理 连接中 和 连接成功
                        if mapy_session.manager.connection.status == .connecting || mapy_session.manager.connection.status == .connected {
                            // 如果已经返回连接， 则避免重复 重置点击状态
                            if mapy_session.manager.connection.status == .connected {
                                mapy_self.mapy_vpnStateClickType = .mapy_none
                            }
                            self?.mapy_vpnChangeBlock?(MAPYVpnStateType(rawValue: mapy_session.manager.connection.status.rawValue) ?? .mapy_invalid)
                            
                        }
                        return
                    }
                    if mapy_self.mapy_vpnStateClickType == .mapy_disConnect { //如果点击了取消连接，只处理 取消连接中 和 取消连接成功
                        if mapy_session.manager.connection.status == .disconnecting || mapy_session.manager.connection.status == .disconnected {
                            // 如果已经返回取消连接， 则避免重复 重置点击状态
                            if mapy_session.manager.connection.status == .disconnected {
                                mapy_self.mapy_vpnStateClickType = .mapy_none
                            }
                            self?.mapy_vpnChangeBlock?(MAPYVpnStateType(rawValue: mapy_session.manager.connection.status.rawValue) ?? .mapy_invalid)
                            
                        }
                        return
                    }
                    if mapy_self.mapy_vpnStateClickType == .mapy_disAndConnect {
                        // 先提供断开
                        if mapy_session.manager.connection.status == .disconnecting || mapy_session.manager.connection.status == .disconnected {
                            
                            if mapy_session.manager.connection.status == .disconnecting {
                                self?.mapy_vpnChangeBlock?(MAPYVpnStateType(rawValue: mapy_session.manager.connection.status.rawValue) ?? .mapy_invalid)
                            }else {
                                // 断开成功之后，开始连接
                                mapy_self.mapy_vpnStateClickType = .mapy_connect
                                mapy_self.mapy_startConnect(mapy_serverModel: mapy_self.mapy_curServerModel)
                            }
                            
                            
                        }
                    }
                }
                
            })
    }
    @objc func mapy_removeVPNChangeNoti() {
        NotificationCenter.default.removeObserver(self, name: mapy_vpnStateChange_noti, object: nil)
    }
}
extension MAPYManager {
    //MARK: - mapy vpn request
    func mapy_vpnList1Request() {
        let mapy_api = MAPYVPNApiList1()
        mapy_api.mapy_statrRequest { response in
            if let mapy_response = response as? String {

                
                self.mapy_saveSrKey(mapy_key: mapy_vpnResList1_key, mapy_value: mapy_response)
                self.mapy_updateDataBaseSmartAddress()
                
            }
        }
    }
    func mapy_vpnList2Request() {
        let mapy_api = MAPYVPNApiList2()
        mapy_api.mapy_statrRequest{ response in
            if let mapy_response = response as? String {
//                self.mapy_pingVPNIPAddressAction(mapy_vpnReqModel: mapy_model, mapy_group: self.pingGroup2, mapy_queue: self.pingQueue2)
                self.mapy_saveSrKey(mapy_key: mapy_vpnResList2_key, mapy_value: mapy_response)
                self.mapy_updateDataBaseListAddress()
            }
        }
    }
    //MARK: - 更新本地数据库的list ip
    func mapy_updateDataBaseListAddress() {
        //TODO: 目前只处理 list1
//        let mapy_reqModel = mapy_getVPNRequestModel(mapy_savePath: mapy_vpnResList1_key)
//        self.mapy_pingVPNIPAddressAction(mapy_vpnReqModel: mapy_reqModel, mapy_group: self.pingGroup2, mapy_queue: self.pingQueue2) {
//            let mapy_models = mapy_reqModel.mapy_crkZQ.mapy_qlHTP.filter { mapy_model in
//                return mapy_model.mapy_pingValue < 800
//            }
//            if mapy_models.count == 0 {
//                return
//            }
//            // 删除旧的 所有地址
//            self.mapy_deleteServeListModels()
//            // 添加新的
//            for mapy_model in mapy_models {
//                self.mapy_createServerModel(mapy_country:mapy_model.mapy_cTvsK,mapy_address: mapy_model.mapy_bTuIq, mapy_password: mapy_reqModel.mapy_crkZQ.mapy_wxFdL, mapy_port: "\(mapy_reqModel.mapy_crkZQ.mapy_eksjN)")
//            }
//            NotificationCenter.default.post(name: mapy_vpnlistUpdate_noti, object: nil)
//        }
        
    }
    //MARK: - 更新本地数据库的smart ip
    func mapy_updateDataBaseSmartAddressNoPing() {
        let mapy_serverModel = self.mapy_getSmartServerModel()
        guard let mapy_serverModel = mapy_serverModel else { return  }
        
        let mapy_reqModel = mapy_getVPNRequestModel(mapy_savePath: mapy_vpnResList1_key)
        // 是否是默认的
        if mapy_serverModel.mapy_address == "195.234.82.185" && mapy_serverModel.mapy_password == "KwmurbWXx.DZVBk6" && mapy_serverModel.mapy_port == "1627" {
            let mapy_models = mapy_reqModel.mapy_crkZQ.mapy_qlHTP//.filter { mapy_model in
             //  return mapy_model.mapy_pingValue < 800
          //  }
            if mapy_models.count == 0 {
                return
            }
            let mapy_count = mapy_models.count
            let mpay_vpnSerModel = mapy_models[Int(arc4random_uniform(UInt32(mapy_count)))]
            mapy_serverModel.mapy_address = mpay_vpnSerModel.mapy_bTuIq
            mapy_serverModel.mapy_country = mpay_vpnSerModel.mapy_cTvsK
            mapy_serverModel.mapy_password = mapy_reqModel.mapy_crkZQ.mapy_wxFdL
            mapy_serverModel.mapy_method = "chacha20-ietf-poly1305"
            mapy_serverModel.mapy_port = "\(mapy_reqModel.mapy_crkZQ.mapy_eksjN)"
            mapy_serverModel.mapy_country = mpay_vpnSerModel.mapy_cTvsK
            self.mapy_updateDataModel()
            
            
        }
    }
    func mapy_updateDataBaseSmartAddress() {
        let mapy_reqModel = mapy_getVPNRequestModel(mapy_savePath: mapy_vpnResList1_key)
        self.mapy_pingVPNIPAddressAction(mapy_vpnReqModel: mapy_reqModel, mapy_group: self.pingGroup1, mapy_queue: self.pingQueue1) {
            let mapy_serverModel = self.mapy_getSmartServerModel()
            guard let mapy_serverModel = mapy_serverModel else {
                let mapy_models = mapy_reqModel.mapy_crkZQ.mapy_qlHTP.filter { mapy_model in
                    return mapy_model.mapy_pingValue < 800
                }
                if mapy_models.count == 0 {
                    return
                }
                let mapy_count = mapy_models.count
                let mpay_vpnSerModel = mapy_models[Int(arc4random_uniform(UInt32(mapy_count)))]
                let mapy_model = self.mapy_createServerModel(mapy_country:mpay_vpnSerModel.mapy_cTvsK, mapy_address: mpay_vpnSerModel.mapy_bTuIq, mapy_password: mapy_reqModel.mapy_crkZQ.mapy_wxFdL, mapy_port: "\(mapy_reqModel.mapy_crkZQ.mapy_eksjN)", mapy_smart: true)
                
                mapy_model.mapy_select = true
                self.mapy_updateDataModel()
                NotificationCenter.default.post(name: mapy_vpnlistUpdate_noti, object: nil)
                //TODO: list 2
                            // 删除旧的 所有地址
                            self.mapy_deleteServeListModels()
                            // 添加新的
                            for mapy_model in mapy_models {
                                self.mapy_createServerModel(mapy_country:mapy_model.mapy_cTvsK,mapy_address: mapy_model.mapy_bTuIq, mapy_password: mapy_reqModel.mapy_crkZQ.mapy_wxFdL, mapy_port: "\(mapy_reqModel.mapy_crkZQ.mapy_eksjN)")
                            }
                            NotificationCenter.default.post(name: mapy_vpnlistUpdate_noti, object: nil)
                return
                
            }
           
            let mapy_models = mapy_reqModel.mapy_crkZQ.mapy_qlHTP.filter { mapy_model in
                return mapy_model.mapy_pingValue < 800
            }
            if mapy_models.count == 0 {
                return
            }
            let mapy_count = mapy_models.count
            let mpay_vpnSerModel = mapy_models[Int(arc4random_uniform(UInt32(mapy_count)))]
            mapy_serverModel.mapy_address = mpay_vpnSerModel.mapy_bTuIq
            mapy_serverModel.mapy_country = mpay_vpnSerModel.mapy_cTvsK
            mapy_serverModel.mapy_password = mapy_reqModel.mapy_crkZQ.mapy_wxFdL
            mapy_serverModel.mapy_method = "chacha20-ietf-poly1305"
            mapy_serverModel.mapy_port = "\(mapy_reqModel.mapy_crkZQ.mapy_eksjN)"
            mapy_serverModel.mapy_country = mpay_vpnSerModel.mapy_cTvsK
            self.mapy_updateDataModel()
            NotificationCenter.default.post(name: mapy_vpnlistUpdate_noti, object: nil)
            //TODO: list 2
                        // 删除旧的 所有地址
                        self.mapy_deleteServeListModels()
                        // 添加新的
                        for mapy_model in mapy_models {
                            self.mapy_createServerModel(mapy_country:mapy_model.mapy_cTvsK,mapy_address: mapy_model.mapy_bTuIq, mapy_password: mapy_reqModel.mapy_crkZQ.mapy_wxFdL, mapy_port: "\(mapy_reqModel.mapy_crkZQ.mapy_eksjN)")
                        }
                        NotificationCenter.default.post(name: mapy_vpnlistUpdate_noti, object: nil)
        }
    }
    func mapy_updateSelectServerModels() {
        let _ = MAPYManager.mapy_manager.mapy_getSelectServerModels().map { mapy_model in
            mapy_model.mapy_select = false
        }
    }
    //MARK: - 连接 smart 节点
    func mapy_connectSmartAction() {
        mapy_updateDataBaseSmartAddressNoPing()
        mapy_updateSelectServerModels()
        let mapy_serverModel = mapy_getSmartServerModel()
        mapy_serverModel?.mapy_select = true
        mapy_updateDataModel()
        if mapy_vpnCurStateType == .mapy_connected {
            mapy_vpnStateClickType = .mapy_disAndConnect
            mapy_stopConnect { _ in

            }
            mapy_curServerModel = mapy_serverModel
            return
        }
        mapy_curServerModel = mapy_serverModel
        mapy_vpnStateClickType = .mapy_connect
        self.mapy_startConnect(mapy_serverModel: mapy_serverModel)
    }
    //MARK: - 连接 list 节点
    func mapy_connectListAction(mapy_serverModel: MAPYServerModel?) {
        if mapy_vpnCurStateType == .mapy_connected {
            mapy_vpnStateClickType = .mapy_disAndConnect
            // 先取消连接
            mapy_stopConnect { mapy_state in

            }
            mapy_curServerModel = mapy_serverModel
            return
        }
        mapy_vpnStateClickType = .mapy_connect
        mapy_curServerModel = mapy_serverModel
        self.mapy_startConnect(mapy_serverModel: mapy_serverModel)
    }
    //MARK: - 连接 选中 节点
    func mapy_connectSelectAddreddAction() {
        mapy_updateDataBaseSmartAddressNoPing()
        var mapy_serverModel = mapy_getSelectServerModel()
        if mapy_serverModel == nil {
            mapy_serverModel = mapy_getSmartServerModel()
            mapy_serverModel?.mapy_select = true
        }
        if mapy_vpnCurStateType == .mapy_connected {
            mapy_vpnStateClickType = .mapy_disAndConnect
            // 先取消连接
            mapy_stopConnect { mapy_state in

            }
            mapy_curServerModel = mapy_serverModel
            return
        }
        mapy_curServerModel = mapy_serverModel
        mapy_vpnStateClickType = .mapy_connect
        self.mapy_startConnect(mapy_serverModel: mapy_serverModel)
    }
}

//MARK: - mapy vpn ping
extension MAPYManager {
    @objc func mapy_pingVPNIPAddressAction(mapy_vpnReqModel: MAPYVPNRequestModel, mapy_group: DispatchGroup, mapy_queue: DispatchQueue, mapy_complete:(()->())? = nil) {
        if self.mapy_vpnCurStateType == .mapy_connected {
            mapy_complete?()
            return
        }
        print("开始ping 节点==========================================")
        for mapy_reqModel in mapy_vpnReqModel.mapy_crkZQ.mapy_qlHTP {
            mapy_group.enter() // 进入 Dispatch Group
            mapy_queue.async {
                
                let pinger = try? SwiftyPing(host: mapy_reqModel.mapy_bTuIq, configuration: PingConfiguration(interval: 0.5, with: 5), queue: mapy_queue)
                pinger?.observer = { (response) in
                    let duration = response.duration
                    mapy_reqModel.mapy_pingValue = NSInteger(duration*1000)
                    print("\(mapy_reqModel.mapy_bTuIq) 节点ping结束==========================================\(NSInteger(duration*1000))")
                    mapy_group.leave()
                }
                pinger?.targetCount = 1
                try? pinger?.startPinging()
                
            }
        }
        mapy_group.notify(queue: .main) {
            print("All pings are complete")
            mapy_complete?()
        }
        
    }
}

//MARK: - 获取 ip 地址信息
import Alamofire
extension MAPYManager {
    @objc func mapy_ipInfoVPNAction(mapy_serModels: [MAPYServerModel]) {
       
        for mapy_serModel in mapy_serModels {
            AF.request("http://ipinfo.io/\(mapy_serModel.mapy_address ?? "")?token=\(mapy_ipTokenUUID)", method: .get, parameters: nil){ mapy_request in
                // 设置超时时间
                mapy_request.timeoutInterval = 15
            }.responseString { mapy_response in
                switch mapy_response.result {
                case .failure(_):
                    return
                case .success(_):
                    break
                }
                guard let mapy_ipInfoString = mapy_response.value else {
                    
                    return
                }
                let mapy_ipScanModel = MAPYIPScanModel(JSONString: mapy_ipInfoString)
                mapy_serModel.mapy_city = mapy_ipScanModel?.mapy_city
                self.mapy_updateDataModel()
                print(mapy_serModel.mapy_address, mapy_ipScanModel?.mapy_city)
            }
        }
        
        
    }
}

